package server

import (
	"coolcar/shared/auth"
	"net"

	"go.uber.org/zap"
	"google.golang.org/grpc"
)

// gRPCConfig defines a grpc server.
type gRPCConfig struct {
	name              string
	addr              string
	authPublicKeyFile string
	registerFunc      func(*grpc.Server)
	Logger            *zap.Logger
}

// NewGRPCConfig init *gRPCConfig.
func NewGRPCConfig(name, addr, authPublicKeyFile string, registerFunc func(*grpc.Server), logger *zap.Logger) *gRPCConfig {
	return &gRPCConfig{
		name:              name,
		addr:              addr,
		authPublicKeyFile: authPublicKeyFile,
		registerFunc:      registerFunc,
		Logger:            logger,
	}
}

// RunGRPCServer runs a grpc server
func RunGRPCServer(c *gRPCConfig) error {
	nameField := zap.String("name", c.name)
	lis, err := net.Listen("tcp", c.addr)
	if err != nil {
		c.Logger.Fatal("cannot listen", nameField, zap.Error(err))
	}

	var opts []grpc.ServerOption
	if c.authPublicKeyFile != "" {
		in, err := auth.Interceptor(c.authPublicKeyFile)
		if err != nil {
			c.Logger.Fatal("cannot create auth interceptor", nameField, zap.Error(err))
		}
		opts = append(opts, grpc.UnaryInterceptor(in))
	}

	s := grpc.NewServer(opts...)
	c.registerFunc(s)

	c.Logger.Info("server started", nameField, zap.String("addr", c.addr))
	return s.Serve(lis)
}
